package org.rqb.socket;

import lombok.extern.slf4j.Slf4j;
import org.rqb.entry.Message;
import org.rqb.frame.ChatFrame;
import org.rqb.frame.MyFrame;
import org.rqb.panel.QueryLANDevicesPanel;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

import static org.rqb.Constant.EXIST;

@Slf4j
public class MySocket {
    private static MySocket mySocket;


    private MyFrame myFrame;
    private Map<String,Socket> socketMap = new HashMap<>();
    private ServerSocket serverSocket;


    private QueryLANDevicesPanel queryLANDevicesPanel;


    public static MySocket getInstance(){
        if (mySocket == null){
            mySocket = new MySocket();
        }
        return mySocket;
    }




    public void startListenPort(int port) {
        try {
            serverSocket = new ServerSocket(port);
            while (true) {
                try {
                    Socket socket = serverSocket.accept();
                    // 开启聊天监听线程
                    new Thread(new ChatThread(socket)).start();

                } catch (IOException e) {
                    log.error("Error accepting connection", e);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void sendShowWindowRequest(int port) {
        try (Socket clientSocket = new Socket("localhost", port); ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream())) {
            // 如果 clientSocket 为空或者已关闭，则创建新的 socket

            Message message = new Message("localhost", "localhost", EXIST, Message.MessageType.TEXT);
            out.writeObject(message);
            out.flush();


        } catch (IOException e) {
            log.error("发送消息异常", e);
        }
    }



    public boolean sendMessage(Message message, int port) {
        String targetHost = message.getReceiver();
        Socket socket = socketMap.get(targetHost);

        try {
            // 如果 socket 为空或已关闭，创建新的 socket
            if (socket == null || socket.isClosed()) {
                socket = new Socket(targetHost, port);
                socketMap.put(targetHost, socket);
            }

            // 创建输出流
            try (ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream())) {
                outputStream.reset();
                outputStream.writeObject(message);
                outputStream.flush();
            }
            return true;

        } catch (IOException e) {
            log.error("发送消息时出现异常，目标主机：{}，端口：{}，错误信息：{}", targetHost, port, e.getMessage());
            // 弹出消息提示框
            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(null, "对方不在线，不能接受到消息" + e.getMessage(), "发送失败", JOptionPane.ERROR_MESSAGE);
            });
            // 如果 socket 创建失败或发送失败，移除无效的 socket
            socketMap.remove(targetHost);
            return false;
        }
    }

    public void closeClientSocket(Socket clientSocket,ObjectOutputStream out) {
        try {
            if (out != null) {
                out.close();
            }
            if (clientSocket != null) {
                clientSocket.close();
            }
        } catch (IOException e) {
            log.error("关闭socket错误", e);
        }
    }

    public boolean isPortInUse(int port) {
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            serverSocket.setReuseAddress(true);
            return false;
        } catch (IOException e) {
            return true;
        }
    }

    public void startSocketServer(int port, MyFrame myFrame) {
        this.myFrame = myFrame;
        Thread socketThread = new Thread(() -> {
            startListenPort(port);
        });
        socketThread.setDaemon(true); // 将线程设置为守护线程
        socketThread.start();
    }

    public void addQueryLanDevicesPanel(QueryLANDevicesPanel queryLANDevicesPanel) {
        this.queryLANDevicesPanel = queryLANDevicesPanel;
    }

    class ChatThread implements Runnable { //端口监听线程
        private Socket socket;
        private ObjectInputStream inputStream;
        private ObjectOutputStream outputStream;
        private volatile boolean running = true; // 控制线程的运行状态

        public ChatThread(Socket socket) {
            this.socket = socket;
            try {
                this.outputStream = new ObjectOutputStream(socket.getOutputStream());
                this.inputStream = new ObjectInputStream(socket.getInputStream());
            } catch (IOException e) {
                log.error("流初始化失败", e);
                running = false; // 失败则停止线程
            }
        }

        @Override
        public void run() {
            while (running) {
                try {
                    Message message = (Message) inputStream.readObject();
                    if (message.getMessageType() == Message.MessageType.TEXT) {
                        //将用户ip添加到集合中
                        socketMap.put(message.getSender(),socket);
                        if (EXIST.equals(message.getContent())) {
                            // 收到客户端请求后，显示JFrame
                            if (myFrame != null) {
                                SwingUtilities.invokeLater(() -> myFrame.displayAtTheForefront());
                                running = false;
                            }
                           continue;
                        }
                        //展示消息
//                        log.info(message.getContent());
                        showReceiverMessage(message);

                    }
                } catch (EOFException e) {
                    log.info("Connection closed.");
                    running = false;
//                    socketMap.remove(socket);
                } catch (IOException | ClassNotFoundException e) {
                    log.error("Error reading message", e);
                    running = false;
                    socketMap.remove(socket);
                }
            }
            closeResources();
        }

        public void closeResources() {
            running = false;
            socketMap.remove(socket);
            try {
                if (inputStream != null) inputStream.close();
                if (outputStream != null) outputStream.close();
                if (socket != null && !socket.isClosed()) socket.close();
            } catch (IOException e) {
                log.error("Error closing resources", e);
            }
        }
    }

    private void showReceiverMessage(Message message) {
        String other = message.getSender();
        Map<String, ChatFrame> chatFrameMap = queryLANDevicesPanel.getChatFrameMap();
        ChatFrame chatFrame = chatFrameMap.get(other);
        if (chatFrame == null){
            chatFrame = new ChatFrame(queryLANDevicesPanel.getCurrentIp(), other);
            chatFrameMap.put(other,chatFrame);
        }
        //将按钮设置为有未读消息
        queryLANDevicesPanel.setBtnColor(other,Color.CYAN);
        //展示消息
        chatFrame.receiveMessage(message);
    }
}
